<p>XML standard allows the use of entities, declared in the DOCTYPE of the document, which can be <a
href="https://www.w3.org/TR/xml/#sec-internal-ent">internal</a> or <a href="https://www.w3.org/TR/xml/#sec-external-ent">external</a>.</p>
<p>When parsing the XML file, the content of the external entities is retrieved from an external storage such as the file system or network, which may
lead, if no restrictions are put in place, to arbitrary file disclosures or <a
href="https://www.owasp.org/index.php/Server_Side_Request_Forgery">server-side request forgery (SSRF)</a> vulnerabilities.</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE person [
  &lt;!ENTITY file SYSTEM "file:///etc/passwd"&gt;
  &lt;!ENTITY ssrf SYSTEM "https://internal.network/sensitive_information"&gt;
]&gt;

&lt;person&gt;
  &lt;name&gt;&amp;file;&lt;/name&gt;
  &lt;city&gt;&amp;ssrf;&lt;/city&gt;
  &lt;age&gt;18&lt;/age&gt;
&lt;/person&gt;
</pre>
<p>It’s recommended to limit resolution of external entities by using one of these solutions:</p>
<ul>
  <li> If DOCTYPE is not necessary, completely disable all DOCTYPE declarations. </li>
  <li> If external entities are not necessary, completely disable their declarations. </li>
  <li> If external entities are necessary then:
    <ul>
      <li> Use XML processor features, if available, to authorize only required protocols (eg: https). </li>
      <li> And use an entity resolver (and optionally an XML Catalog) to resolve only trusted entities. == Noncompliant Code Example </li>
    </ul>  </li>
</ul>
<p>For <a href="https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/DocumentBuilderFactory.html">DocumentBuilder</a>, <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/SAXParserFactory.html">SAXParser</a>, <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/stream/XMLInputFactory.html">XMLInput</a>, <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/transform/TransformerFactory.html">Transformer</a> and <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/validation/SchemaFactory.html">Schema</a> JAPX factories:</p>
<pre>
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // Noncompliant

SAXParserFactory factory = SAXParserFactory.newInstance(); // Noncompliant

XMLInputFactory factory = XMLInputFactory.newInstance(); // Noncompliant

TransformerFactory factory = javax.xml.transform.TransformerFactory.newInstance();  // Noncompliant

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);  // Noncompliant
</pre>
<p>For <a href="https://dom4j.github.io/">Dom4j</a> library:</p>
<pre>
SAXReader xmlReader = new SAXReader(); // Noncompliant
</pre>
<p>For <a href="http://www.jdom.org/">Jdom2</a> library:</p>
<pre>
SAXBuilder builder = new SAXBuilder(); // Noncompliant
</pre>
<h2>Compliant Solution</h2>
<p>For <a href="https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/DocumentBuilderFactory.html">DocumentBuilder</a>, <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/parsers/SAXParserFactory.html">SAXParser</a>, <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/stream/XMLInputFactory.html">XMLInput</a>, <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/transform/TransformerFactory.html">Transformer</a> and <a
href="https://docs.oracle.com/javase/9/docs/api/javax/xml/validation/SchemaFactory.html">Schema</a> JAPX factories:</p>
<pre>
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// to be compliant, completely disable DOCTYPE declaration:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// or completely disable external entities declarations:
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// or prohibit the use of all protocols by external entities:
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");


SAXParserFactory factory = SAXParserFactory.newInstance();
// to be compliant, completely disable DOCTYPE declaration:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// or completely disable external entities declarations:
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// or prohibit the use of all protocols by external entities:
SAXParser parser = factory.newSAXParser(); // Noncompliant
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

XMLInputFactory factory = XMLInputFactory.newInstance();
// to be compliant, completely disable DOCTYPE declaration:
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
// or completely disable external entities declarations:
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
// or prohibit the use of all protocols by external entities:
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

TransformerFactory factory = javax.xml.transform.TransformerFactory.newInstance();
// to be compliant, prohibit the use of all protocols by external entities:
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// to be compliant, completely disable DOCTYPE declaration:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// or prohibit the use of all protocols by external entities:
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
</pre>
<p>For <a href="https://dom4j.github.io/">Dom4j</a> library:</p>
<pre>
SAXReader xmlReader = new SAXReader();
xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
</pre>
<p>For <a href="http://www.jdom.org/">Jdom2</a> library:</p>
<pre>
SAXBuilder builder = new SAXBuilder();
builder.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
builder.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
</pre>
<h2>See</h2>
<ul>
  <li> <a
  href="https://docs.oracle.com/en/java/javase/13/security/java-api-xml-processing-jaxp-security-guide.html#GUID-8CD65EF5-D113-4D5C-A564-B875C8625FAC">Oracle Java Documentation</a> - XML External Entity Injection Attack </li>
  <li> <a href="https://www.owasp.org/index.php/Top_10-2017_A4-XML_External_Entities_(XXE)">OWASP Top 10 2017 Category A4</a> - XML External Entities
  (XXE) </li>
  <li> <a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java">OWASP XXE Prevention Cheat
  Sheet</a> </li>
  <li> <a href="http://cwe.mitre.org/data/definitions/611.html">MITRE, CWE-611</a> - Information Exposure Through XML External Entity Reference </li>
  <li> <a href="http://cwe.mitre.org/data/definitions/827.html">MITRE, CWE-827</a> - Improper Control of Document Type Definition </li>
</ul>

